import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadCallable {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        // 使用 callable 来计算 1 + 2 + 3 + .. + 1000
        // 先创建 callable 实例

        Callable<Integer> callable = new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                // 这个方法就相当于 Runnable 的 run方法 run 方法的返回值是 void
                // 此处的 call 方法的返回值是 Integer
                int sum = 0 ;
                for (int i = 1; i <= 1000; i++) {
                    sum+=i;
                }
                return sum;
            }
        };

        // 需要构造到一个Thread里面进行使用
        FutureTask<Integer> futureTask = new FutureTask<>(callable);
        Thread thread = new Thread(futureTask); // 没办法直接把callable传入到thread的构造方法里面,需要套上一层其他的辅助类 FutureTask
        thread.start();


        // FutureTask 表示未来的一个任务 ,那么为什么这样呢?
        // 举个例子 : 比如你要吃麻辣烫, 当你选好菜之后,递给前台帮你做,那么等做好之后怎么才知道哪一个是属于你的呢,毕竟有这么多人一块选菜
        // 这时候就需要一个小票来帮助 知道 哪一份麻辣烫是属于谁的
        // 最后在凭借这小票来呼叫客人吃饭
        // FutureTask 就起到小票的作用
        // callable 是后厨做好麻辣烫

        //在主线程中调用futureTask.get() 能够阻塞等待新线程计算完毕. 并获取到 FutureTask 中的结果
        Integer result = futureTask.get(); // 会抛出两个异常
        System.out.println(result); // 获取到这里的结果
        // get 会发生阻塞, 知道 callable 执行完毕 , get 才阻塞完成 , 才获取到结果

        // 相关面试题
        //介绍下 Callable 是什么
        //Callable 是一个 interface . 相当于把线程封装了一个 "返回值". 方便程序猿借助多线程的方式计算
        //结果.
        //Callable 和 Runnable 相对, 都是描述一个 "任务". Callable 描述的是带有返回值的任务,
        //Runnable 描述的是不带返回值的任务.
        //Callable 通常需要搭配 FutureTask 来使用. FutureTask 用来保存 Callable 的返回结果. 因为
        //Callable 往往是在另一个线程中执行的, 啥时候执行完并不确定.
        //FutureTask 就可以负责这个等待结果出来的工作.
    }
}
